home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / sbin / update-initramfs < prev    next >
Encoding:
Text File  |  2007-04-10  |  9.0 KB  |  503 lines

  1. #!/bin/sh
  2.  
  3. STATEDIR=/var/lib/initramfs-tools
  4. BOOTDIR=/boot
  5. CONF=/etc/initramfs-tools/update-initramfs.conf
  6. KPKGCONF=/etc/kernel-img.conf
  7.  
  8. set -e
  9.  
  10. [ -r ${CONF} ] && . ${CONF}
  11.  
  12. usage()
  13. {
  14.     if [ -n "${1}" ]; then
  15.         printf "${@}\n\n" >&2
  16.     fi
  17.     cat >&2 << EOF
  18. Usage: ${0} [OPTION]...
  19.  
  20. Options:
  21.  -k [version]    Specify kernel version or 'all'
  22.  -c        Create a new initramfs
  23.  -u        Update an existing initramfs
  24.  -d        Remove an existing initramfs
  25.  -t        Take over a custom initramfs with this one
  26.  -b        Set alternate boot directory
  27.  -v        Be verbose
  28.  -h        This message
  29.  
  30. EOF
  31.     exit 1
  32. }
  33.  
  34. mild_panic()
  35. {
  36.     if [ -n "${1}" ]; then
  37.         printf "${@}\n" >&2
  38.     fi
  39.     exit 0
  40. }
  41.  
  42. panic()
  43. {
  44.     if [ -n "${1}" ]; then
  45.         printf "${@}\n" >&2
  46.     fi
  47.     exit 1
  48. }
  49.  
  50. verbose()
  51. {
  52.     if [ "${verbose}" = 1 ]; then
  53.         printf "${@}\n"
  54.     fi
  55. }
  56.  
  57. version_exists()
  58. {
  59.     [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
  60.     return $?
  61. }
  62.  
  63. set_initramfs()
  64. {
  65.     initramfs="${BOOTDIR}/initrd.img-${version}"
  66. }
  67.  
  68.  
  69. # backup initramfs while running
  70. backup_initramfs()
  71. {
  72.     [ ! -r "${initramfs}" ] && return 0
  73.     initramfs_bak="${initramfs}.dpkg-bak"
  74.     [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
  75.     mv -f "${initramfs}" "${initramfs_bak}"
  76.     verbose "Keeping ${initramfs_bak}"
  77. }
  78.  
  79. # keep booted initramfs
  80. backup_booted_initramfs()
  81. {
  82.     initramfs_bak="${initramfs}.dpkg-bak"
  83.  
  84.     # first time run thus no backup
  85.     [ ! -r "${initramfs_bak}" ] && return 0
  86.  
  87.     # chroot
  88.     [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
  89.  
  90.     # no kept backup wanted
  91.     [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
  92.  
  93.     # no backup yet
  94.     if [ ! -r "${initramfs}.bak" ]; then
  95.         mv -f ${initramfs_bak} "${initramfs}.bak"
  96.         verbose "Backup ${initramfs}.bak"
  97.         return 0
  98.     fi
  99.  
  100.     # keep booted initramfs
  101.     uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
  102.     if [ -n "$uptime_days" ]; then
  103.         boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
  104.     fi
  105.     if [ -n "${boot_initramfs}" ]; then
  106.         mv -f "${initramfs_bak}" "${initramfs}.bak"
  107.         verbose "Backup ${initramfs}.bak"
  108.         return 0
  109.     fi
  110.     verbose "Removing current backup ${initramfs_bak}"
  111.     rm -f ${initramfs_bak}
  112. }
  113.  
  114. # restore initramfs backup
  115. restore_initramfs()
  116. {
  117.     [ -z "${initramfs_bak}" ] && return 0
  118.     mv -f "${initramfs_bak}" "${initramfs}"
  119.     verbose "Restoring ${initramfs_bak}"
  120. }
  121.  
  122.  
  123. generate_initramfs()
  124. {
  125.     echo "update-initramfs: Generating ${initramfs}"
  126.     OPTS="-o"
  127.     if [ "${verbose}" = 1 ]; then
  128.         OPTS="-v ${OPTS}"
  129.     fi
  130.     if mkinitramfs ${OPTS} "${initramfs}" "${version}"; then
  131.         set_sha1
  132.     else
  133.         mkinitramfs_return="$?"
  134.         restore_initramfs
  135.         if [ "$mkinitramfs_return" = "2" ]; then
  136.             # minversion wasn't met, exit 0
  137.             exit 0
  138.         fi
  139.         echo "update-initramfs: failed for ${initramfs}"
  140.         exit $mkinitramfs_return
  141.     fi
  142. }
  143.  
  144. # lilo call
  145. run_lilo()
  146. {
  147.     # show lilo errors on failure
  148.     if ! lilo -t  > /dev/null 2>&1 ; then
  149.         echo "update-initramfs: lilo run failed for ${initramfs}:"
  150.         echo
  151.         lilo -t
  152.     fi
  153.     lilo
  154. }
  155.  
  156. # check if lilo is on mbr
  157. mbr_check()
  158. {
  159.     # check out lilo.conf for validity
  160.     boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
  161.     [ -z "${boot}" ] && return 0
  162.     case ${boot} in
  163.     /dev/md*)
  164.         if [ -r /proc/mdstat ]; then
  165.             MD=${boot#/dev/}
  166.             boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
  167.             /proc/mdstat)"
  168.         fi
  169.         ;;
  170.     esac
  171.     [ ! -r "${boot}" ] && return 0
  172.     dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
  173.         && run_lilo && return 0
  174.  
  175.     # try to discover grub and be happy
  176.     [ -r /boot/grub/menu.lst ] \
  177.         && groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
  178.             /boot/grub/menu.lst)
  179.     [ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
  180.         && dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
  181.     [ -n "${dev}" ] && [ -r ${dev} ] \
  182.         && dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
  183.         | grep -q GRUB && return 0
  184.     
  185.     # no idea which bootloader is used
  186.     echo
  187.     echo "WARNING: grub and lilo installed."
  188.     echo "If you use grub as bootloader everything is fine."
  189.     echo "If you use lilo as bootloader you must run lilo!"
  190.     echo
  191. }
  192.  
  193. # Invoke bootloader
  194. run_bootloader()
  195. {
  196.     # if both lilo and grub around, figure out if lilo needs to be run
  197.     if [ -x /sbin/grub ] || [ -e /boot/grub/menu.lst ] \
  198.     || [ -x /usr/sbin/grub ]; then
  199.         if [ -e /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  200.             [ -r "${KPKGCONF}" ] && \
  201.             do_b=$(awk  '/^do_bootloader/{print $3}' "${KPKGCONF}")
  202.             if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
  203.                 || [ "${do_b}" = "YES" ]; then
  204.                 run_lilo
  205.                 return 0
  206.             elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
  207.                 || [ "${do_b}" = "NO" ]; then
  208.                 return 0
  209.             else
  210.                 mbr_check
  211.                 return 0
  212.             fi
  213.         fi
  214.         return 0
  215.     fi
  216.     if [ -r /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  217.         run_lilo
  218.         return 0
  219.     fi
  220.     if [ -x /sbin/elilo ]; then
  221.         elilo
  222.         return 0
  223.     fi
  224.     if [ -r /etc/zipl.conf ]; then
  225.         zipl
  226.     fi
  227. }
  228.  
  229. compare_sha1()
  230. {
  231.     sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
  232.     return $?
  233. }
  234.  
  235. # Note that this must overwrite so that updates work.
  236. set_sha1()
  237. {
  238.     sha1sum "${initramfs}" > "${STATEDIR}/${version}"
  239. }
  240.  
  241. delete_sha1()
  242. {
  243.     rm -f "${STATEDIR}/${version}"
  244. }
  245.  
  246. # ro /boot is not modified
  247. ro_boot_check()
  248. {
  249.     [ -r /proc/mounts ] || return 0
  250.     boot_opts=$(awk '/boot/{if (match($4, /ro/) && $2 == "/boot")
  251.         print "ro"}' /proc/mounts)
  252.     if [ -n "${boot_opts}" ]; then
  253.         echo "WARNING: /boot is ro mounted."
  254.         echo "update-initramfs: Not updating ${initramfs}"
  255.         exit 0
  256.     fi
  257. }
  258.  
  259. get_sorted_versions()
  260. {
  261.     version_list=""
  262.  
  263.     for gsv_x in "${STATEDIR}"/*; do
  264.         gsv_x="$(basename "${gsv_x}")"
  265.         if [ "${gsv_x}" = '*' ]; then
  266.             return 0
  267.         fi
  268.         worklist=""
  269.         for gsv_i in $version_list; do
  270.             if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
  271.                 worklist="${worklist} ${gsv_x} ${gsv_i}"
  272.                 gsv_x=""
  273.             else
  274.                 worklist="${worklist} ${gsv_i}"
  275.             fi
  276.         done
  277.         if [ "${gsv_x}" != "" ]; then
  278.             worklist="${worklist} ${gsv_x}"
  279.         fi
  280.         version_list="${worklist}"
  281.     done
  282.  
  283.     verbose "Available versions: ${version_list}"
  284. }
  285.  
  286. set_current_version()
  287. {
  288.     if [ -f /boot/initrd.img-`uname -r` ]; then
  289.         version=`uname -r`
  290.     fi
  291. }
  292.  
  293. set_linked_version()
  294. {
  295.     if [ -L /initrd.img ]; then
  296.         linktarget="$(basename "$(readlink /initrd.img)")"
  297.     fi
  298.  
  299.     if [ -L /boot/initrd.img ]; then
  300.         linktarget="$(basename "$(readlink /boot/initrd.img)")"
  301.     fi
  302.  
  303.     if [ -z "${linktarget}" ]; then
  304.         return
  305.     fi
  306.  
  307.     version="${linktarget##initrd.img-}"
  308. }
  309.  
  310. set_highest_version()
  311. {
  312.     get_sorted_versions
  313.     set -- ${version_list}
  314.     version=${1}
  315. }
  316.  
  317. create()
  318. {
  319.     if [ -z "${version}" ]; then
  320.         usage "Create mode requires a version argument"
  321.     fi
  322.  
  323.     set_initramfs
  324.  
  325.     if [ "${takeover}" = 0 ]; then
  326.         if version_exists "${version}"; then
  327.             panic "Cannot create version ${version}: already exists"
  328.         fi
  329.  
  330.         if [ -e "${initramfs}" ]; then
  331.             panic "${initramfs} already exists, cannot create."
  332.         fi
  333.     fi
  334.  
  335.     generate_initramfs
  336. }
  337.  
  338. update()
  339. {
  340.     if [ "${update_initramfs}" = "no" ]; then
  341.         echo "update-initramfs: Not updating initramfs."
  342.         exit 0
  343.     fi
  344.  
  345.     if [ -z "${version}" ]; then
  346.         set_linked_version
  347.     fi
  348.  
  349.     if [ -z "${version}" ]; then
  350.         set_highest_version
  351.     fi
  352.  
  353.     if [ -z "${version}" ]; then
  354.         set_current_version
  355.     fi
  356.  
  357.     if [ -z "${version}" ]; then
  358.         verbose "Nothing to do, exiting."
  359.         exit 0
  360.     fi
  361.  
  362.     set_initramfs
  363.  
  364.     ro_boot_check
  365.  
  366.     altered_check
  367.  
  368.     backup_initramfs
  369.  
  370.     generate_initramfs
  371.  
  372.     run_bootloader
  373.  
  374.     backup_booted_initramfs
  375. }
  376.  
  377. delete()
  378. {
  379.     if [ -z "${version}" ]; then
  380.         usage "Delete mode requires a version argument"
  381.     fi
  382.  
  383.     set_initramfs
  384.  
  385.     if [ ! -e "${initramfs}" ]; then
  386.         panic "Cannot delete ${initramfs}, doesn't exist."
  387.     fi
  388.  
  389.     if ! version_exists "${version}"; then
  390.         panic "Cannot delete version ${version}: Not created by this utility."
  391.     fi
  392.  
  393.     altered_check
  394.  
  395.     echo "update-initramfs: Deleting ${initramfs}"
  396.  
  397.     delete_sha1
  398.  
  399.     rm -f "${initramfs}"
  400. }
  401.  
  402. # Check for update mode on existing and modified initramfs
  403. altered_check()
  404. {
  405.     # No check on takeover
  406.     [ "${takeover}" = 1 ] && return 0
  407.     if [ ! -e "${initramfs}" ]; then
  408.         mild_panic "${initramfs} does not exist. Cannot update."
  409.     fi
  410.     if ! compare_sha1; then
  411.         mild_panic "${initramfs} has been altered. Cannot update."
  412.     fi
  413. }
  414.  
  415. # Defaults
  416. verbose=0
  417. yes=0
  418. # We default to takeover=1 in Ubuntu, but not Debian
  419. takeover=1
  420.  
  421. ##
  422.  
  423. while getopts "k:cudyvtb:h?" flag; do
  424.     case "${flag}" in
  425.     k)
  426.         version="${OPTARG}"
  427.         ;;
  428.     c)
  429.         mode="c"
  430.         ;;
  431.     d)
  432.         mode="d"
  433.         ;;
  434.     u)
  435.         mode="u"
  436.         ;;
  437.     v)
  438.         verbose="1"
  439.         ;;
  440.     y)
  441.         yes="1"
  442.         ;;
  443.     t)
  444.         takeover="1"
  445.         ;;
  446.     b)
  447.         BOOTDIR="${OPTARG}"
  448.         if [ ! -d "${BOOTDIR}" ]; then
  449.             echo "Error: ${BOOTDIR} is not a directory."
  450.             exit 1
  451.         fi
  452.         ;;
  453.     h|?)
  454.         usage
  455.         ;;
  456.     esac
  457. done
  458.  
  459. # Validate arguments
  460. if [ -z "${mode}" ]; then
  461.     usage "You must specify at least one of -c, -u, or -d."
  462. fi
  463.  
  464. if [ "${version}" = "all" ]; then
  465.     : FIXME check for --yes, and if not ask are you sure
  466.     get_sorted_versions
  467.     if [ -z "${version_list}" ]; then
  468.         verbose "Nothing to do, exiting."
  469.         exit 0
  470.     fi
  471.  
  472.     OPTS="-b ${BOOTDIR}"
  473.     if [ "${verbose}" = "1" ]; then
  474.         OPTS="${OPTS} -v"
  475.     fi
  476.     if [ "${takeover}" = "1" ]; then
  477.         OPTS="${OPTS} -t"
  478.     fi
  479.     if [ "${yes}" = "1" ]; then
  480.         OPTS="${OPTS} -y"
  481.     fi
  482.     for u_version in ${version_list}; do
  483.         # Don't stop if one version doesn't work.
  484.         set +e
  485.         verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
  486.         "${0}" -${mode} -k "${u_version}" ${OPTS}
  487.         set -e
  488.     done
  489.     exit 0
  490. fi
  491.  
  492. case "${mode}" in
  493.     c)
  494.         create
  495.         ;;
  496.     d)
  497.         delete
  498.         ;;
  499.     u)
  500.         update
  501.         ;;
  502. esac
  503.